  <!-- 这里的value随便给的值20230602,防止该option被选中 -->
<template>
  <el-select ref='mySelect' v-model="sonValue" :multiple='_checkBox' @visible-change="visibleChangeHandle" @remove-tag="removeTagHandle" :collapse-tags='_checkBox' placeholder="请选择" :popper-append-to-body="popperAppendToBody" clearable @clear="clearSelect" :disabled="disabled">
    <el-option class="option-class" disabled value="20230602">
      <el-input size='small' placeholder="关键字查询" v-model="filterText" suffix-icon="el-icon-search" clearable v-if='showFilter'></el-input>
      <div class="tree-dom">
        <el-tree class="my-tree" v-if='!refresh' ref="myTree" @node-click='clickHandle' :data='data' :props="defaultProps" :default-expand-all="true" :show-checkbox="_checkBox" node-key="id" @check-change="checkChangeHandle" :filter-node-method="filterNode" :expand-on-click-node="false" :default-checked-keys="_checkBox ? value : []" :check-strictly="checkStrictly" :highlight-current="true">
          <span slot-scope="{ node , data }" class="content" :class="{ 'disabled': data.isDisabled }">
            <slot :node="node" :data="data">
              <span> {{ node.label }}</span>
            </slot>
          </span>
        </el-tree>
      </div>
    </el-option>
  </el-select>
</template>
<script>
// 多选的回显：tree的:default-checked-keys="_checkBox?value:[]"默认勾选以后触发了方法回调；
// 单选的回显：直接在created里面显示
export default {
  name: "treeSelect",
  model: {
    // 需要双向绑定的 props 变量名称，也就是父组件通过 v-model 与子组件双向绑定的变量
    prop: 'value',
    // 定义由 $emit 传递变量的名称
    event: 'changeValue'
  },
  props: {
    // v-model传递的值
    value: {
      typeof: Array,
    },
    data: {
      typeof: Array,
      require: true
    },
    showFilter: {
      type: Boolean,
      default: true
    },
    checkStrictly: {
      typeof: Boolean,
      default: false
    },
    checkBox: {
      typeof: Boolean,
      default: false
    },
    popperAppendToBody: {
      typeof: Boolean,
      default: false
    },
    disabled: {
      typeof: Boolean,
      default: false
    },
    defaultProps: {
      default: () => {
        return {
          children: 'children',
          label: 'label',
          isLeaf: 'hasChildren',
        }
      }
    },
  },
  data() {
    return {
      sonValue: null,// 内部值

      selectIds: [],// 已勾选id集合
      datalist: [],// 已勾选的树节点集合
      _checkBox: false,//是否开启勾选
      lock: false,//锁，内部修改值的时候不需要再触发一次

      refresh: false,
      filterText: null,
    }
  },
  created() {
    // 允许直接写checkBox或者checkBox=true开启该功能
    this._checkBox = this.checkBox === '' ? true : this.checkBox
    // 设置初值防止表单验证问题
    this.sonValue = this._checkBox ? [] : null
  },
  mounted() {
    this.setSonValue();
  },
  watch: {
    value: {
      handler(val) {
        this.setSonValue();
      },
    },
    filterText(val) {
      if (this.sonValue?.length == 0 || !this.sonValue) {
        // 修改filter的时候占位以解决表单奇怪的验证问题
        this.$emit("changeValue", this._checkBox ? ['20230626'] : '20230626')
      }
      // 此处val是string
      if (!!!val) {
        this.refresh = true
        this.$nextTick(() => {
          this.refresh = false
        })
      } else {
        this.$nextTick(() => {
          this.$refs.myTree.filter(val);
        })
      }
    },
  },
  methods: {
    // 窗体消失的时候隐藏并还原数据
    visibleChangeHandle(isShow) {
      if (!isShow) {
        if (this.sonValue?.length == 0 || !this.sonValue) this.$emit("changeValue", this._checkBox ? [] : null)
      }
    },
    filterNode(value, data, node) {
      if (!value) return true
      if (this.showFilter) {
        //element-UI tree树形控件搜索过滤节点，不展示子节点的问题
        let parentNode = node.parent
        let labels = [node.label]
        let level = 1
        while (level < node.level) {
          labels = [...labels, parentNode.label]
          parentNode = parentNode.parent
          level++
        }
        return labels.some(label => label.indexOf(value) !== -1)
      } else {
        return !!this.compareOneEqualTwo(data[this.defaultProps.label], value)
      }
    },
    compareOneEqualTwo(prototype, searchStr) {
      var reg = new RegExp(searchStr, "i");
      return (prototype.match(reg) != null);
    },
    // 多选移除tag事件
    removeTagHandle(value) {
      this.datalist.forEach(v => {
        if (v.label === value) {
          this.$refs.myTree.setChecked(v.id, false)
        }
      })
    },
    // 筛选了选中项
    filterByCondition(item, list, param) {
      // 如果是基站
      if (item.type == 2) {
        list.push(item[param]);
      }
    },
    setSonValue() {
      // 存在勾选框的时候是数组，否则是字符串
      if (this._checkBox) {
        this.sonValue = [];
        this.$nextTick(() => {
          this.datalist = this.$refs.myTree?.getCheckedNodes() ?? []
          this.datalist.filter((v) => {
            this.filterByCondition(v, this.sonValue, 'label')
          })
          if (this.value?.length) {
            this.selectIds = this.value ?? [];
            // 防止循环调用
            if (this.lock) {
              this.lock = false
              return
            }
            this.checkChangeHandle();
          }
        })
      } else {
        // 防止循环调用
        if (this.lock) {
          this.lock = false
          return
        }
        // 如果有值则回显
        this.sonValue = this.value != null ? (this.queryTree(this.data, 'id', this.value)?.label || null) : null;
        this.$refs.myTree.setCurrentKey(this.value);
      }
    },
    // 查询树某个节点
    queryTree(tree, param = 'value', value) {
      let stack = [];
      stack = stack.concat(tree);
      while (stack.length) {
        const temp = stack.shift();
        if (temp.children) {
          stack = stack.concat(temp.children);
        }
        if (temp[param] === value) {
          return temp;
        }
      }
      return '';
    },
    // 清空按钮
    clearSelect() {
      this.$refs.myTree.setCheckedKeys([]);
      this.$emit("changeValue", null)
      this.$emit('afterClick', {})  // 如果父组件想获取多个数据传给后端
    },
    // 勾选触发事件
    checkChangeHandle(data, self, child) {
      this.datalist = this.$refs.myTree.getCheckedNodes()
      this.selectIds = [];
      this.datalist.filter((v) => {
        this.filterByCondition(v, this.selectIds, 'id')
      })
      this.$emit("changeValue", this.selectIds)
      this.lock = true;
    },
    // 点击触发事件
    clickHandle(data, node) {
      if (data.isDisabled) return;
      // 如果是勾选框，点击事件就不触发
      if (this._checkBox) return
      this.$emit("changeValue", data.id)
      this.$emit('afterClick', data)  // 如果父组件想获取多个数据传给后端
      this.sonValue = data.label
      this.$refs.mySelect.blur();
    },
  },
}
</script>
<style scoped lang="less">
@realHeight: 310px;

.option-class {
  height: auto;
  padding: 5px !important;
  margin: 0;
  overflow: auto;
  cursor: default !important;
}

::v-deep {
  .el-select-dropdown__wrap {
    max-height: 600px;
  }
}

.tree-dom {
  height: @realHeight - 34px - 10px;
  overflow: auto;
  margin-top: 10px;
}

.my-tree {
  font-size: 14px;
  user-select: none;
  display: flex;
  flex-direction: column;

  .content {
    display: inline-flex;
    align-items: center;

    &.disabled {
      color: #eee !important;
      cursor: not-allowed !important;
    }
  }

  ::v-deep {
    .el-tree-node > .el-tree-node__children {
      overflow: visible;
    }

    .el-tree-node {
      min-width: -webkit-max-content;
    }
  }

  span {
    div,
    img {
      position: relative;
      top: 3px;
    }
  }
}
</style>